﻿using ArtMath.Core.Data;
using ArtMath.Setting;
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;

namespace ArtMath.Core.Helper
{
    public static class Painter
    {
        public static void DrawPoint(this Graphics gra, Pen p, Brush brush, PointD Pxy, double size)
        {
            if (Pxy.IsPaintable)
            {
                RectangleF rect = new RectangleF((float)(Pxy.X - size), (float)(Pxy.Y - size), 
                    (float)(size * 2), (float)(size * 2));
                gra.FillEllipse(brush, rect);
                gra.DrawEllipse(p, rect);
            }
        }
        public static void DrawPoint(this Graphics gra, PointD Pxy)
        {
            gra.DrawPoint(new Pen(Settings.Instance.VirtualPointOutlineColor, (float)Settings.Instance.VirtualPointOutlineWidth), 
                new SolidBrush(Settings.Instance.VirtualPointFillColor), Pxy, Settings.Instance.VirtualPointSize);
        }
        public static void DrawLineSegment(this Graphics gra, Pen p, PointD pt1, PointD pt2)
        {
            if (pt1.IsPaintable && pt2.IsPaintable)
            {
                gra.DrawLine(p, pt1.ToPointF(), pt2.ToPointF());
            }
        }
        public static Pen VirtualLinePen
        {
            get
            {
                return new Pen(Settings.Instance.VirtualLineColor, (float)Settings.Instance.VirtualLineWidth)
                {
                    DashStyle = Settings.Instance.VirtualLineDashStyle,//画虚线性能较低
                    LineJoin = LineJoin.Round
                };
            }
        }
        public static Pen VirtualVectorPen
        {
            get
            {
                Pen p = VirtualLinePen;
                p.CustomEndCap = new AdjustableArrowCap(5, 6, true);
                return p;
            }
        }
        public static void DrawLineSegment(this Graphics gra, PointD pt1, PointD pt2)
        {
            gra.DrawLineSegment(VirtualLinePen, pt1, pt2);
        }
        public static void DrawVector(this Graphics gra, PointD pt1, PointD pt2)
        {
            gra.DrawLineSegment(VirtualVectorPen, pt1, pt2);
        }
        public static void DrawArc(this Graphics gra, Pen p, PointD Pcenter, double rotate, double Px, double Py, double Pstart, double Psweep)
        {
            if (Px != 0 && Py != 0)
            {
                Transform(gra, Pcenter, rotate, () =>
                {
                    if (p != null)
                    {
                        gra.DrawArc(p, (float)-Px, (float)-Py, (float)(Px * 2), (float)(Py * 2),
                            (float)Pstart, (float)Psweep);
                    }
                });
            }
        }
        public static void DrawArc(this Graphics gra, PointD Pcenter, double rotate, double Px, double Py, double Pstart, double Psweep)
        {
            gra.DrawArc(VirtualLinePen, Pcenter, rotate, Px, Py, Pstart, Psweep);
        }
        public static void DrawCircle(this Graphics gra, Pen p, Brush brush, PointD Pcenter, double rotate, double Px, double Py)
        {
            if (Px != 0 && Py != 0)
            {
                Transform(gra, Pcenter, rotate, () =>
                {
                    RectangleF rect = new RectangleF((float)-Px, (float)-Py, (float)(Px * 2), (float)(Py * 2));
                    if (brush != null)
                    {
                        gra.FillEllipse(brush, rect);
                    }
                    if (p != null)
                    {
                        gra.DrawEllipse(p, rect);
                    }
                });
            }
        }
        public static SolidBrush VirtualBrush
        {
            get { return new SolidBrush(Settings.Instance.VirtualClosedShapeFillColor); }
        }
        public static void DrawCircle(this Graphics gra, PointD Pcenter, double rotate, double Px, double Py)
        {
            gra.DrawCircle(VirtualLinePen, VirtualBrush, Pcenter, rotate, Px, Py);
        }
        public static void DrawSector(this Graphics gra, Pen p, Brush brush, PointD Pcenter, double rotate, double Px, double Py, double Pstart, double Psweep)
        {
            if (Px == 0 || Py == 0) return;
            Transform(gra, Pcenter, rotate, () =>
            {
                if (brush != null)
                {
                    gra.FillPie(brush, (float)-Px, (float)-Py, (float)(Px * 2), (float)(Py * 2), (float)Pstart, (float)Psweep);
                }
                if (p != null)
                {
                    gra.DrawPie(p, (float)-Px, (float)-Py, (float)(Px * 2), (float)(Py * 2), (float)Pstart, (float)Psweep);
                }
            });
        }
        public static void DrawSector(this Graphics gra, PointD Pcenter, double rotate, double Px, double Py, double Pstart, double Psweep)
        {
            gra.DrawSector(VirtualLinePen, VirtualBrush, Pcenter, rotate, Px, Py, Pstart, Psweep);
        }
        public static void Transform(this Graphics gra, PointD Pcenter, double rotate, Action draw)
        {
            if (Pcenter.IsPaintable && rotate.IsNumber() && draw != null)
            {
                gra.TranslateTransform((float)Pcenter.X, (float)Pcenter.Y);
                gra.RotateTransform((float)rotate);
                draw();
                gra.RotateTransform((float)-rotate);
                gra.TranslateTransform((float)-Pcenter.X, (float)-Pcenter.Y);
            }
        }
        public static ImageAttributes GetTransparentAttribute(float transparency)
        {
            ImageAttributes ia = new ImageAttributes();
            ia.SetColorMatrix(new ColorMatrix(new float[][]
            {
                new float[] { 1, 0, 0, 0, 0 },
                new float[] { 0, 1, 0, 0, 0 },
                new float[] { 0, 0, 1, 0, 0 },
                new float[] { 0, 0, 0, transparency, 0 },
                new float[] { 0, 0, 0, 0, 1 },
            }));
            return ia;
        }
    }
}
